package org.ch02.hw.demo12;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

/**
 * 基于内省完成
 *
 * @author ZJL
 * @date 2025-03-25
 */
public class BeanUtil {

    /**
     * 1、设置何意对象的属性值
     *
     * @param bean         Bean 对象
     * @param propertyName 字段名称
     * @param value        设置字段的值
     */
    public static void setProperty(Object bean, String propertyName, Object value) {
        try {
            // 实例化 PropertyDescriptor 对象 - 指向某个类的某个属性
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, bean.getClass());
            // 调用 setter 方法
            propertyDescriptor.getWriteMethod().invoke(bean, value);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 2、获取任意对象的属性值
     *
     * @param bean         Bean 对象
     * @param propertyName 字段名称
     * @return
     */
    public static Object getProperty(Object bean, String propertyName) {
        try {
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, bean.getClass());
            return propertyDescriptor.getReadMethod().invoke(bean);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 3、复制某个对象的属性值到另一个对象中
     *
     * @param sourceBean 源 Bean 对象
     * @param targetBean 目标 Bean 对象
     */
    public static void copyProperties(Object sourceBean, Object targetBean) {
        if (sourceBean.getClass() != targetBean.getClass()) {
            throw new RuntimeException("Bean 对象类型不匹配,无法复制");
        }
        try {
            BeanInfo sourceBeanInfo = Introspector.getBeanInfo(sourceBean.getClass(), Object.class);
            // 获取 Bean 对象中的所有属性
            PropertyDescriptor[] sourceBeanInfoPropertyDescriptors = sourceBeanInfo.getPropertyDescriptors();
            // 循环遍历所有的属性
            for (PropertyDescriptor sourceBeanInfoPropertyDescriptor : sourceBeanInfoPropertyDescriptors) {

                // 获取属性名
                String propertyName = sourceBeanInfoPropertyDescriptor.getName();

                // 获取属性值
                Object propertyValue = getProperty(sourceBean, propertyName);

                // 给目标对象赋值
                setProperty(targetBean, propertyName, propertyValue);

//                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(sourceBeanInfoPropertyDescriptor.getName(), sourceBean.getClass());
//                propertyDescriptor.getWriteMethod().invoke(targetBean, sourceBeanInfoPropertyDescriptor.getReadMethod().invoke(sourceBean));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
